﻿namespace PerpetuumSoft.InstrumentationPDA.Mathematics
{
    using System;
    using System.Drawing;
    using System.Reflection;
    using System.Runtime.InteropServices;

    [StructLayout(LayoutKind.Sequential)]
    public struct Vector
    {
        private decimal x;
        private decimal y;
        public static readonly Vector Empty;
        public decimal X
        {
            get
            {
                return this.x;
            }
            set
            {
                this.x = value;
            }
        }
        public decimal Width
        {
            get
            {
                return this.x;
            }
            set
            {
                this.x = value;
            }
        }
        public decimal Y
        {
            get
            {
                return this.y;
            }
            set
            {
                this.y = value;
            }
        }
        public decimal Height
        {
            get
            {
                return this.y;
            }
            set
            {
                this.y = value;
            }
        }
        public decimal Rotation
        {
            get
            {
                double num = Math.Atan2((double) this.Y, (double) this.X);
                if (num < 0.0)
                {
                    num += 6.2831853071795862;
                }
                return (decimal) num;
            }
            set
            {
                Vector vector = FromPolar(this.Lenght, value);
                this.X = vector.X;
                this.Y = vector.Y;
            }
        }
        public decimal Lenght
        {
            get
            {
                return this.Abs();
            }
            set
            {
                Vector vector = FromPolar(value, this.Rotation);
                this.X = vector.X;
                this.Y = vector.Y;
            }
        }
        public decimal this[Direction direction]
        {
            get
            {
                if (direction == Direction.X)
                {
                    return this.X;
                }
                return this.Y;
            }
            set
            {
                if (direction == Direction.X)
                {
                    this.X = value;
                }
                else
                {
                    this.Y = value;
                }
            }
        }
        public Vector(decimal x, decimal y)
        {
            this.x = x;
            this.y = y;
        }

        public Vector(Point point) : this(point.X, point.Y)
        {
        }

        public Vector(Size size) : this(size.Width, size.Height)
        {
        }

        public Vector(SizeF size) : this((decimal) size.Width, (decimal) size.Height)
        {
        }

        public Vector(Direction direction, decimal primary, decimal secodary)
        {
            if (direction == Direction.X)
            {
                this.x = primary;
                this.y = secodary;
            }
            else
            {
                this.y = primary;
                this.x = secodary;
            }
        }

        public Vector(Direction direction, Point point) : this(direction, point.X, point.Y)
        {
        }

        public static Vector FromPolar(decimal Lenght, decimal angle)
        {
            return new Vector(Lenght * ((decimal) Math.Cos((double) angle)), Lenght * ((decimal) Math.Sin((double) angle)));
        }

        public override int GetHashCode()
        {
            return 0;
        }

        public override bool Equals(object o)
        {
            return base.Equals(o);
        }

        public decimal Abs()
        {
            return (decimal) Math.Sqrt((double) ((this.x * this.x) + (this.y * this.y)));
        }

        public Vector Quant(decimal xGrid, decimal yGrid)
        {
            decimal x;
            decimal y;
            if (xGrid != 0M)
            {
                x = Math.Round((decimal) (this.x / xGrid)) * xGrid;
            }
            else
            {
                x = this.x;
            }
            if (yGrid != 0M)
            {
                y = Math.Round((decimal) (this.y / yGrid)) * yGrid;
            }
            else
            {
                y = this.y;
            }
            return new Vector(x, y);
        }

        public Vector QuantX(decimal xGrid)
        {
            decimal x;
            if (xGrid != 0M)
            {
                x = Math.Round((decimal) (this.x / xGrid)) * xGrid;
            }
            else
            {
                x = this.x;
            }
            return new Vector(x, this.y);
        }

        public Vector QuantY(decimal yGrid)
        {
            decimal y;
            if (yGrid != 0M)
            {
                y = Math.Round((decimal) (this.y / yGrid)) * yGrid;
            }
            else
            {
                y = this.y;
            }
            return new Vector(this.x, y);
        }

        public decimal GetSecondaryValue(Direction direction)
        {
            if (direction == Direction.X)
            {
                return this.Y;
            }
            return this.X;
        }

        public bool IsEmpty
        {
            get
            {
                return ((this.x == 0M) && (this.y == 0M));
            }
        }
        public static Vector operator +(Vector v)
        {
            return v;
        }

        public static Vector operator -(Vector v)
        {
            return new Vector(-v.X, -v.Y);
        }

        public static Vector operator +(Vector a, Vector b)
        {
            return new Vector(a.X + b.X, a.Y + b.Y);
        }

        public static Vector operator -(Vector a, Vector b)
        {
            return new Vector(a.X - b.X, a.Y - b.Y);
        }

        public static Vector operator *(Vector v, decimal a)
        {
            return new Vector(v.X * a, v.Y * a);
        }

        public static Vector operator *(Vector a, Vector b)
        {
            return new Vector(a.X * b.X, a.Y * b.Y);
        }

        public static Vector operator /(Vector v, decimal a)
        {
            return new Vector(v.X / a, v.Y / a);
        }

        public static bool operator ==(Vector v1, Vector v2)
        {
            return ((v1.X == v2.X) && (v1.Y == v2.Y));
        }

        public static bool operator !=(Vector v1, Vector v2)
        {
            if (v1.X == v2.X)
            {
                return !(v1.Y == v2.Y);
            }
            return true;
        }

        public override string ToString()
        {
            return ("{" + this.x.ToString() + ";" + this.y.ToString() + "}");
        }

        public static implicit operator Vector(Point point)
        {
            return new Vector(point);
        }

        public static implicit operator Vector(Size size)
        {
            return new Vector(size);
        }

        public static implicit operator Vector(SizeF size)
        {
            return new Vector(size);
        }

        public static implicit operator SizeF(Vector vector)
        {
            return new SizeF((float) vector.X, (float) vector.Y);
        }

        public static explicit operator Point(Vector vector)
        {
            return new Point((int) vector.X, (int) vector.Y);
        }

        public static explicit operator Size(Vector vector)
        {
            return new Size((int) vector.X, (int) vector.Y);
        }

        public Point Truncate()
        {
            return new Point((int) this.x, (int) this.y);
        }

        public Size TruncateSize()
        {
            return new Size((int) this.x, (int) this.y);
        }

        static Vector()
        {
            Empty = new Vector();
        }
    }
}

